<template>
    <div>
        <p class="top-title">当前选中：{{ curConfig.label }}</p>
        <el-select placeholder="请选择" v-model="selectType" style="margin-bottom: 15px;">
            <el-option v-for="item in typeOption" :key="item.value" :label="item.label" :value="item.value" />
        </el-select>
        <el-row style="margin-bottom: 15px;">
            <el-tooltip content="添加控件" placement="top">
                <el-button color="#13ce66" circle @click="add">
                    <el-icon color="#fff">
                        <Plus />
                    </el-icon>
                </el-button>
            </el-tooltip>
            <el-tooltip content="删除控件" placement="top">
                <el-button color="#ff4949" circle @click="deleteElement">
                    <el-icon color="#fff">
                        <Minus />
                    </el-icon>
                </el-button>
            </el-tooltip>
        </el-row>
        <el-divider></el-divider>
        <el-row>
            <template v-if="showControl(curConfig.boxType, 'offset')">
                <el-col class="slider-title">偏移</el-col>
                <el-col :span="23" :offset="1">
                    <el-slider v-model="curConfig.offset" show-input :max="24" />
                </el-col>
                <el-col class="slider-title">宽度</el-col>
                <el-col :span="23" :offset="1">
                    <el-slider v-model="curConfig.width" show-input :max="24" :min='1' />
                </el-col>
            </template>
            <el-col>
                <md-input disabled>类型: {{ curConfig.boxType }}</md-input>
            </el-col>
            <template v-if="showControl(curConfig.boxType, 'id')">
                <el-col>
                    <md-input disabled>id: {{ activeId }}</md-input>
                </el-col>
            </template>
            <template v-if="showControl(curConfig.boxType, 'name')">
                <el-col>
                    <md-input v-model="curConfig.name">Name</md-input>
                </el-col>
            </template>
            <el-col>
                <md-input v-model="curConfig.label">Label</md-input>
            </el-col>
            <template v-if="showControl(curConfig.boxType, 'default')">
                <el-col v-if="curConfig.boxType !== 'number'">
                    <md-input v-model="curConfig.default">Default</md-input>
                </el-col>
                <el-col v-else>
                    <md-input v-model="curConfig.default" type="number" :min="curConfig.min" :max="curConfig.max"
                        :step="curConfig.step">Default</md-input>
                </el-col>
            </template>
            <template v-if="showControl(curConfig.boxType, 'rules')">
                <el-col>
                    <md-input v-model="curConfig.rules">Rules</md-input>
                </el-col>
            </template>
            <template v-if="showControl(curConfig.boxType, 'hidden')">
                <el-col>
                    <el-switch v-model="curConfig.visible" active-color="#13ce66" inactive-color="#ff4949"
                        active-text="提交页显示该控件" inactive-text="提交页隐藏该控件" class="switch">
                    </el-switch>
                </el-col>
            </template>
            <el-row>
                <el-col>
                    <template v-if="showControl(curConfig.boxType, 'placeholder')">
                        <md-input v-model="curConfig.placeholder">Placeholder</md-input>
                    </template>
                    <template v-if="showControl(curConfig.boxType, 'disabled')">
                        <span class="text-title">Disabled：</span>
                        <el-switch v-model="curConfig.disabled" active-color="#13ce66" inactive-color="#ff4949"
                            active-text="是" inactive-text="否">
                        </el-switch>
                    </template>
                </el-col>
                <el-col v-if="showControl(curConfig.boxType, 'required')">
                    <span class="text-title">Required：</span>
                    <el-switch v-model="curConfig.required" active-color="#13ce66" inactive-color="#ff4949"
                        active-text="是" inactive-text="否">
                    </el-switch>
                </el-col>
                <el-col v-if="showControl(curConfig.boxType, 'FileOrDir')">
                    <span class="text-title">FileOrDir：</span>
                    <el-radio-group v-model="curConfig.fileOrDir" class="ml-4">
                        <el-radio label="file" size="large">file</el-radio>
                        <el-radio label="dir" size="large">dir</el-radio>
                        <el-radio label="all" size="large">all</el-radio>
                    </el-radio-group>
                </el-col>
            </el-row>
            <template v-if="showControl(curConfig.boxType, 'type')">
                <el-col>
                    <md-input v-model="curConfig.type">Type</md-input>
                </el-col>
            </template>
            <template v-if="showControl(curConfig.boxType, 'minmaxstep')">
                <el-col>
                    <md-input v-model="curConfig.min" type="number">Min</md-input>
                </el-col>
                <el-col>
                    <md-input v-model="curConfig.max" type="number">Max</md-input>
                </el-col>
                <el-col>
                    <md-input v-model="curConfig.step" type="number">Step</md-input>
                </el-col>
            </template>
            <template v-if="curConfig.boxType === 'list'">
                <select-view v-model="(curConfig.selectOptions as selectOptionsType)"
                    v-model:selected="(curConfig.selected as string)"></select-view>
            </template>
        </el-row>
    </div>
</template>
<script lang="ts" setup>
import selectView from './selectView.vue';
import { ref, watch, onMounted, reactive } from 'vue';
import mdInput from '@/components/MDinput/index.vue'
import { copy } from '@/api/api'
import { ElNotification } from 'element-plus'
import type { treeDataType, configType, nodeType, selectOptionsType } from './index.vue'

import { showControl } from './showControl'

type idStoreType = {
    [type: string]: number[]
}

let props = defineProps<{
    tree: treeDataType,
    activeId: string
}>()
let emit = defineEmits<{
    (e: 'update:tree', arg: treeDataType): void
    (e: 'update:activeId', arg: string): void
}
>()
let selectType = ref<string>()
let typeOption = [
    {
        label: 'container',
        value: 'container'
    },
    {
        label: 'info',
        value: 'info'
    },
    {
        label: 'text',
        value: 'text'
    },
    {
        label: 'number',
        value: 'number'
    },
    {
        label: 'password',
        value: 'password'
    },
    {
        label: 'textarea',
        value: 'textarea'
    },
    {
        label: 'rfb',
        value: 'rfb'
    },
    {
        label: 'rfbPath',
        value: 'rfbPath'
    },
    {
        label: 'list',
        value: 'list'
    },
]
let idStore = ref<idStoreType>({
    container: [],
    info: [],
    text: [],
    number: [],
    password: [],
    textarea: [],
    rfb: [],
    rfbPath: [],
    list: []
})
let baseConfig: configType = {
    id: '',
    offset: 0,
    width: 24,
    boxType: '',
    label: '',
    visible: true,
}
let makeBaseConfig = (type: string) => {
    let config: configType = copy(baseConfig)
    switch (type) {
        case 'info':
            break;
        case 'text':
            config.name = ''
            config.disabled = false
            config.required = false
            config.placeholder = ''
            config.default = ''
            config.rules = ''
            break;
        case 'password':
            config.name = ''
            config.required = false
            config.placeholder = ''
            config.rules = ''
            break;
        case 'number':
            config.name = ''
            config.disabled = false
            config.required = false
            config.placeholder = ''
            config.default = ''
            config.min = '1'
            config.max = '10'
            config.step = '1'
            break;
        case 'textarea':
            config.name = ''
            config.placeholder = ''
            config.disabled = false
            break;
        case 'rfb':
            config.name = ''
            config.placeholder = ''
            config.required = false
            config.fileOrDir = 'file'
            config.default = ''
            config.rules = ''
            break;
        case 'rfbPath':
            config.name = ''
            config.placeholder = ''
            config.required = false
            config.fileOrDir = 'file'
            config.default = ''
            config.rules = ''
            break;
        case 'list':
            config.name = ''
            config.placeholder = '请选择'
            config.required = false
            config.selected = ''
            config.selectOptions = [{ label: '', value: '', number: false, disabled: false }]
            break;
    }
    return config
}

let curRoot = ref('root')
let curConfig = ref<configType>(props.tree.root.config)
let find = (tree: treeDataType, target: string): nodeType | undefined => {           //获取target节点
    for (let key in tree) {
        if (key === target) {
            return tree[key]
        } else {
            let isFind = find(tree[key].children, target)
            if (isFind) {
                return isFind
            }
        }
    }
}

let findId = (tree: treeDataType, newStore: idStoreType): void => {           //获取所有
    for (let key in tree) {
        if (key === 'root') {
            findId(tree[key].children, newStore)
            return
        }
        let boxType = tree[key].config.boxType
        console.log(tree[key].config.id)
        let id = tree[key].config.id.match(/\d/g)?.join('')!
        console.log(id)
        newStore[boxType].push(Number(id))
        findId(tree[key].children, newStore)
    }
}
let findParent = (tree: treeDataType, target: string, pre: string): string | undefined => {            //获取target节点的父容器，如果target本身是容器，返回本身
    for (let key in tree) {
        if (key === target) {
            if (tree[key].config.boxType === 'container') return key
            return pre
        } else {
            let isFind = findParent(tree[key].children, target, key)
            if (isFind) {
                return isFind
            }
        }
    }
}
let findContainerParent = (tree: treeDataType, target: string, pre: string): string | undefined => {            //获取target节点的父容器
    for (let key in tree) {
        if (key === target) {
            return pre
        } else {
            let isFind = findContainerParent(tree[key].children, target, key)
            if (isFind) {
                return isFind
            }
        }
    }
}
let makeId = (type: string): number => {                   //获取递增的id，1,2,3,4,5  如果3已存在，直接获得4
    for (let i in idStore.value[type]) {
        let index = Number(i)
        if (idStore.value[type][i] !== index + 1) {
            idStore.value[type].splice(index, 0, index + 1)
            return index + 1
        }
    }
    idStore.value[type].push(idStore.value[type].length + 1)
    return idStore.value[type].length
}

//添加操作
let add = () => {
    if (!selectType.value) {
        return ElNotification({
            title: '请选择控件',
            type: 'warning',
            duration: 2000
        })
    }
    let id = selectType.value + makeId(selectType.value)
    let config = makeBaseConfig(selectType.value)
    config.boxType = selectType.value
    config.label = id
    config.id = id
    find(props.tree, curRoot.value)!.children[id] = { config, children: {} }
    emit('update:activeId', id)
    // pushHistory()            //记录历史操作
    ElNotification({
        title: `添加${id}成功`,
        type: 'success'
    })
}

//删除操作
let deleteElement = () => {
    if (props.activeId === 'root') {
        return ElNotification({
            title: '不能删除根组件',
            type: 'error',
            duration: 2000
        })
    }
    let changeId = ''      //删完之后activeId切换到父容器
    let deleteTree: nodeType
    let del = (tree: treeDataType, target: string, parent: string): any => {           //删除节点
        for (let key in tree) {
            if (key === target) {
                changeId = parent
                deleteTree = tree[key]
                delete tree[key]
                return true
            } else {
                let isFind = del(tree[key].children, target, key)
                if (isFind) {
                    return isFind
                }
            }
        }
    }
    let removeId = (id: string) => {                //将idStore中的id删除
        let boxType = id.match(/[a-z A-Z]/g)!.join('')
        let number = Number(id.match(/\d/g)!.join(''))
        for (let i in idStore.value[boxType]) {
            let index = Number(i)
            if (idStore.value[boxType][i] === number) {
                idStore.value[boxType].splice(index, 1)
            }
        }
    }
    let removeTree = (tree: nodeType) => {               //删除节点的id和子节点的id
        //递归获取所有子节点id
        let idArr: string[] = []
        function getId(curTree: nodeType) {
            idArr.push(curTree.config.id)
            for (let key in curTree.children) {
                if (curTree.children[key]) {
                    getId(curTree.children[key])
                }
            }
        }
        getId(tree)
        for (let item of idArr) {
            removeId(item)
        }
    }


    del(props.tree, props.activeId, 'root')
    emit('update:activeId', changeId)        //删除节点后，选中上一层的节点
    removeTree(deleteTree!)
    // pushHistory()                            //记录历史操作
    ElNotification({
        title: `${deleteTree!.config.id}删除成功`,
        type: 'success'
    })
}

//更新当前curconfig和curroot
let refreshCur = () => {
    let cur = find(props.tree, props.activeId)
    // console.log('refresh', props.tree, props.activeId)
    curConfig.value = cur!.config
    curRoot.value = findParent(props.tree, props.activeId, 'root')!
}

{
    // //历史操作保存
    // let history: {
    //     treeDataCopy: treeDataType,
    //     idStoreCopy: {
    //         [type: string]: number[]
    //     }
    // }[] = []

    // //记录历史操作
    // let pushHistory = () => {
    //     let treeDataCopy = copy(props.tree)
    //     let idStoreCopy = copy(idStore.value)
    //     console.log('copy', treeDataCopy)
    //     history.push({ treeDataCopy, idStoreCopy })
    //     console.log(history)
    // }

    // //历史回退
    // let historyBack = () => {
    //     if (history.length === 1) {
    //         return ElNotification({
    //             title: '没有可撤销的操作',
    //             type: 'warning',
    //             duration: 2000
    //         })
    //     }
    //     history.pop()
    //     let last = copy(history[history.length - 1])
    //     emit('update:activeId', 'root')
    //     emit('update:tree', last.treeDataCopy)
    //     idStore.value = last.idStoreCopy
    //     setTimeout(() => refreshCur())
    //     console.log(history)
    //     ElNotification({
    //         title: '撤销成功',
    //         type: 'success',
    //         duration: 1000
    //     })
    // }

    // onMounted(() => {
    //     pushHistory()
    // })

    // watch(() => props.tree, () => {
    //     history[history.length - 1].treeDataCopy = copy(props.tree)    //同步更改的数据到历史中
    //     setTimeout(() => refreshCur())
    // }, { deep: true })
}

watch(() => props.activeId, () => {
    refreshCur()
})
watch(() => props.tree, () => {
    emit('update:tree', props.tree)
    refreshCur()
})

//同级拖拽，交换位置
let tongjiDrag = (parentCommonString: string, idfrom: string, idto: string) => {
    let from = find(props.tree, idfrom)!
    let parentCommon = find(props.tree, parentCommonString)!
    if (parentCommon.config.id === idto) {
        console.log('子元素拖到他的父元素')
        return
    }
    //判断相邻
    let flag = false
    let start = false
    let end = false
    for (let key in parentCommon.children) {
        if (start && !end) {
            end = true
            if (key === idfrom || key === idto) {
                flag = true
            }
        }
        if (key === idfrom || key === idto) {
            start = true
        }
    }
    if (flag) {
        console.log('相邻')
        let fromNode = parentCommon.children[idfrom]
        let toNode = parentCommon.children[idto]
        let obj: any = {}
        for (let key in parentCommon.children) {
            if (key === idto) {
                obj[idfrom] = fromNode
                continue
            }
            if (key === idfrom) {
                obj[idto] = toNode
                continue
            }
            obj[key] = parentCommon.children[key]
        }
        parentCommon.children = obj
        return
    }
    delete parentCommon?.children[idfrom]
    let obj: any = {}
    for (let key in parentCommon.children) {

        obj[key] = parentCommon.children[key]

        console.log(obj)
        if (key === idto) {
            obj[idfrom] = from
        }
    }
    parentCommon.children = obj
    console.log(parentCommon.children)
}
//拖到container里面
let containerDrag = (idfrom: string, idto: string) => {
    let idfromPraentString = findContainerParent(props.tree, idfrom, 'root')
    let idfromPraent = find(props.tree, idfromPraentString!);
    find(props.tree, idto)!.children[idfrom] = idfromPraent!.children[idfrom]
    delete idfromPraent!.children[idfrom]
}
//拖拽处理
let dragto = (idfrom: string, idto: string) => {
    console.log(idfrom, idto)
    if (idfrom === idto) return
    let parentfrom = findParent(props.tree, idfrom, 'root')!
    let parentto = findParent(props.tree, idto, 'root')!
    if (parentfrom === parentto) {
        if (idto === 'root') return
        tongjiDrag(parentfrom, idfrom, idto)

    } else if (parentfrom !== parentto) {
        let parentfromNode = find(props.tree, parentfrom!)
        let parenttoNode = find(props.tree, parentto!)
        if (parenttoNode?.children[idfrom]) {
            if (idto === 'root') return
            tongjiDrag(parentto, idfrom, idto)
            return
        }
        console.log('父转换')
        containerDrag(idfrom, idto)
    }
    refreshCur()
}


let updateId = () => { //更新idStore
    let newStore: idStoreType = {
        container: [],
        info: [],
        text: [],
        number: [],
        password: [],
        textarea: [],
        rfb: [],
        rfbPath: [],
        list: []
    }
    findId(props.tree, newStore)
    for (let key in newStore) {
        newStore[key].sort((a: any, b: any) => a - b)
    }
    console.log(newStore)
    idStore.value = newStore
}

defineExpose({
    idStore,
    dragto,
    updateId
})

</script>
<style lang="less">
.top-title {
    font-size: 16px;
    margin-top: -10px;
    margin-bottom: 5px;
}

.btn {
    width: 60px;
}

.slider-title {
    font-size: 14px;
    color: #409eff;
}

.text-title {
    display: inline-block;
    width: 60px;
    font-size: 14px;
    font-weight: 400;
    padding-right: 20px;
    color: #909399;
}
</style>